(function ($) {
    var y = 0;
    var flag = false;
    var targetTop = 0;
    var calcY = 0;
    var $touchTarget = null;
    var type = '';
    var $year = $('.year');
    var $month = $('.month');
    var $day = $('.day');
    var t1 = 0;
    var animateId = 0;
    var options = {
        cellH: 50, // 每个年份的高度
        inertia: {
            min: 0.7,
            mid: 1.7,
            max: 2.7
        }
    };
    $('.date-wrap').on({
        touchstart: function (e) {
            e.preventDefault();
            $touchTarget = $(e.target).closest('ul');
            if ($touchTarget.length > 0) {
                flag = true;
                clearTimeout(animateId);
                targetTop = ($touchTarget.position().top / options.cellH).toFixed(0) * options.cellH;    // 使用toFixed四舍五入，可以省去判断拖动近一半时的定位问题
                $touchTarget.removeClass('animate').css(top, targetTop);
                type = $touchTarget.data('type');
                t1 = +new Date();    // 滑动开始时间点
                y = e.touches[0].clientY;
            }
        },
        touchmove: function (e) {
            e.preventDefault();
            if (!flag) {
                return;
            }
            calcY = e.touches[0].clientY - y;
            $touchTarget.css('top', targetTop + calcY);
        },
        touchend: function (e) {
            e.preventDefault();

            if (!flag) {
                return;
            }
            flag = false;
            var t2 = +new Date();    // 滑动结束时间点
            var v = Math.abs(calcY) / (t2 - t1);    // 计算滑动速度
            calcY = (calcY / options.cellH).toFixed(0) * options.cellH; // 计算出整数个单元的高度

            var maxTop = ($touchTarget.children().length - 2) * options.cellH; // 计算当前滑动目标的最大top值

            if (v > options.inertia.min) {
                var top2 = 0;
                var level = 400;
                if (level > options.inertia.mid) {
                    level = 500;
                }
                if (calcY < 0) {
                    top2 = targetTop - level;
                    if (top2 < -maxTop) {
                        top2 = -maxTop;
                    }
                } else {
                    top2 = targetTop + level;
                    if (top2 >= 50) {
                        top2 = 50;
                    }
                }
                $touchTarget.addClass('animate').css('top', top2);
                clearTimeout(animateId);
                animateId = setTimeout(function () {
                    $touchTarget.removeClass('animate');
                    if (type == 'month' || type == 'year') {
                        getDaysByDate();
                    }
                    setPickedDate();
                }, 300);

            } else {
                var top1 = targetTop + calcY;

                if (top1 > 50) {
                    top1 = 50;
                } else if (top1 < -maxTop) {
                    top1 = -maxTop;
                }
                $touchTarget.css('top', top1);
                if (type == 'month' || type == 'year') {
                    getDaysByDate();
                }
                setPickedDate();
            }

            calcY = 0;


        }
    });


    var week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];

    function getPickedDate() {
        var ytop = $year.position().top;
        var mtop = $month.position().top;
        var dtop = $day.position().top;

        var yi = Math.abs(ytop / 50 - 1);
        var mi = Math.abs(mtop / 50 - 1);
        var di = Math.abs(dtop / 50 - 1);

        var year = $($year.children().eq(yi)).data('year');
        var month = $($month.children().eq(mi)).data('month');
        var day = $($day.children().eq(di)).data('day');
        return [year, month, day];
    }

    function setPickedDate() {
        var arr = getPickedDate();
        var date = new Date(arr.join('-'));
        $('.datepicker-picked').text(arr.join('-') + ' ' + week[date.getDay()]);
    }

    function getDaysByDate(arrDate) {
        var arr = getPickedDate();
        if (arrDate) {
            arr = arrDate;
        }
        var date = new Date();
        date.setFullYear(arr[0], arr[1], 0);
        var maxDays = date.getDate();
        var totalDays = $day.children().length;
        if (maxDays > totalDays) {
            for (var i = totalDays + 1; i <= maxDays; i++) {
                $day.append('<li data-day="' + i + '">' + i + '</li>');
            }
        } else {
            for (var i = totalDays; i > maxDays; i--) {
                $day.children().eq(i - 1).remove();
            }
            if (arr[2] > maxDays) {
                $day.css('top', -(maxDays - 2) * 50);
            }
        }
    }

    var now = new Date();
    var nowYear = now.getFullYear();
    for (var i = nowYear - 10; i <= nowYear + 10; i++) {
        $year.append('<li data-year="' + i + '">' + i + '</li>');
    }
    function init(_value) {

        var initDate = now;
        if (_value) {
            initDate = new Date(_value);
        }

        var year = initDate.getFullYear();
        var month = initDate.getMonth() + 1;
        var day = initDate.getDate();

        getDaysByDate([year, month, day]);

        month = month < 10 ? '0' + month : month;
        day = day < 10 ? '0' + day : day;

        $year.css('top', -(year - nowYear + 9) * 50);
        $month.css('top', -(month - 2) * 50);
        $day.css('top', -(day - 2) * 50);
        $('.datepicker-picked').text(year + '-' + month + '-' + day + ' ' + week[initDate.getDay()]);
    }

    var trigger = null;
    $('body').on('click', '[data-datepicker]', function () {
        trigger = $(this);
        var v = $(this).val();
        init(v);
        $('.datepicker-cover,.datepicker').show();
    });

    $('.datepicker-cover').on('click', function () {
        $('.datepicker-cover,.datepicker').hide();
    });

    $('.datepicker').on('click', '.datepicker-confirm', function () {
        var arr = getPickedDate();
        trigger.val(arr[0] + '-' + arr[1] + '-' + arr[2]);
        trigger.trigger('change');
        setTimeout(function () {
            $('.datepicker-cover,.datepicker').hide();
        }, 100);
    });
})($);